package com.wh1200.mybatis.xmlless

import com.wh1200.mybatis.xmlless.config.BaseResolverTest
import com.wh1200.mybatis.xmlless.plugin.visitor.ColumnReplaceVisitor
import com.wh1200.mybatis.xmlless.plugin.visitor.SelectVisitor
import com.wh1200.mybatis.xmlless.util.TableInfoProvider
import com.wh1200.xmlless.test.dao.StudentDAO
import com.wh1200.xmlless.test.model.UserAddress
import com.wh1200.xmlless.test.model.UserDetail
import net.sf.jsqlparser.parser.CCJSqlParserUtil
import net.sf.jsqlparser.statement.Statement
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

/**
 *
 * @author 吴昊
 * @date 2023/12/15 23:10
 * @since v4.0.1
 * @version 1.0
 */
class SqlConvertTest : BaseResolverTest(StudentDAO::class.java) {

  @BeforeAll
  override fun init() {
    TypeRegistry.init("com.wh1200.xmlless.test.model")
    TableInfoProvider.getOrInitXmllessTableInfo(JavaClassWrapper(UserDetail::class.java))
    TableInfoProvider.getOrInitXmllessTableInfo(JavaClassWrapper(UserAddress::class.java))
  }

  @Test
  @DisplayName("将sql中引用的对象名称以及对象属性替换为对应的表名称和数据库列名")
  fun test() {
    val sql = """select detail.userId, detail.userAddressId, address.userId, user.name from UserDetail 
      |detail left join UserAddress address on detail.userAddressId = address.id
      |LEFT JOIN User user on address.userId = user.id
      |where detail.userId = 1
    """.trimMargin()
    val statement = convert(sql)
    val expect =
        "SELECT detail.detail_user_id, detail.user_address_id, address.address_user_id, user.name FROM user_detail detail LEFT JOIN user_address address ON detail" +
            ".user_address_id = address.id LEFT JOIN t_user user ON address.address_user_id = user.id WHERE detail" +
            ".detail_user_id = 1"
    assertEquals(expect, statement.toString())
  }

  @Test
  @DisplayName("测试未起别名的处理")
  fun test2() {
    val sql = "select userId from UserDetail"
    val statement = convert(sql)
    val expect = "SELECT detail_user_id FROM user_detail"
    assertEquals(expect, statement.toString())
  }

  @Test
  @DisplayName("测试update语句，不带别名")
  fun testUpdate() {
    val sql = "update UserDetail set userId = 1 where id = 1"
    val statement = convert(sql)
    val expect = "UPDATE user_detail SET detail_user_id = 1 WHERE id = 1"
    assertEquals(expect, statement.toString())
  }

  @Test
  @DisplayName("测试update语句，带别名")
  fun testUpdateWithAlias() {
    val sql = "update UserDetail u set u.userId = 1 where u.id = 1"
    val statement = convert(sql)
    val expect = "UPDATE user_detail u SET u.detail_user_id = 1 WHERE u.id = 1"
    assertEquals(expect, statement.toString())
  }

  @Test
  @DisplayName("测试delete语句, 不带别名")
  fun testDelete() {
    val sql = "delete from UserDetail where id = 1"
    val statement = convert(sql)
    val expect = "DELETE FROM user_detail WHERE id = 1"
    assertEquals(expect, statement.toString())
  }

  private fun convert(sql: String): Statement {
    val statement = CCJSqlParserUtil.parse(sql)
    val visitor = SelectVisitor()
    statement.accept(visitor)
    statement.accept(
        ColumnReplaceVisitor(visitor.getTables())
    )
    return statement
  }

}
